package com.ilxqx.fierce.core;

import cn.hutool.core.util.ReflectUtil;
import cn.hutool.core.util.StrUtil;
import com.ilxqx.fierce.annotation.RequestAction;

import java.lang.reflect.Method;

/**
 * 动作处理
 *
 * @author Venus
 * @since 1.0.0
 */
public final class ActionHandlerDelegate {

    /**
     * 处理动作
     *
     * @param request 请求对象
     * @return 响应结果
     */
    static FierceResponse handleAction(FierceRequest request) {
        // 首先从Service中处理Action
        FierceResponse response = handleServiceAction(request);

        if (response != null) {
            return response;
        }

        response = handleMapperAction(request);

        if (response != null) {
            return response;
        }

        // 找不到待处理的Action
        return handleDefaultAction(request);
    }

    /**
     * 处理Mapper动作
     *
     * @param request 请求对象
     * @return 响应结果
     */
    private static FierceResponse handleMapperAction(FierceRequest request) {
        FierceRequestContext context = FierceRequestContextHolder.get();

        if (context.getMapper() == null) {
            return null;
        }

        Method actionMethod = findActionMethod(context.getMapperClass(), request.getAction());
        if (actionMethod == null) {
            return null;
        }

        return handleResult(
            ActionMethodHandlerDelegate.invokeAction(
                context.getMapper(),
                context.getMapperClass(),
                actionMethod,
                request.getData()
            )
        );
    }

    /**
     * 处理Service工作
     *
     * @param request 请求对象
     * @return 响应结果
     */
    private static FierceResponse handleServiceAction(FierceRequest request) {
        FierceRequestContext context = FierceRequestContextHolder.get();

        Method actionMethod = findActionMethod(context.getServiceClass(), request.getAction());
        if (actionMethod == null) {
            return null;
        }

        return handleResult(
            ActionMethodHandlerDelegate.invokeAction(
                context.getService(),
                context.getServiceClass(),
                actionMethod,
                request.getData()
            )
        );
    }

    /**
     * 处理返回结果
     *
     * @param result 结果对象
     * @return 标准响应结果
     */
    private static FierceResponse handleResult(Object result) {
        if (result instanceof FierceResponse) {
            return (FierceResponse) result;
        }

        // 默认则按成功处理
        return FierceResponse.succeed(result);
    }

    /**
     * 寻找目标动作方法
     *
     * @param targetClass 目标类
     * @param targetAction 目标动作
     * @return 方法对象
     */
    private static Method findActionMethod(Class<?> targetClass, String targetAction) {
        Method[] methods = ReflectUtil.getPublicMethods(targetClass);
        for (Method method : methods) {
            if (method.isAnnotationPresent(RequestAction.class)) {
                String action = method.getAnnotation(RequestAction.class).value();

                if (StrUtil.isBlank(action)) {
                    action = method.getName();
                }

                if (StrUtil.equals(action, targetAction)) {
                    return method;
                }
            }
        }

        return null;
    }

    /**
     * 处理默认动作
     *
     * @param request 请求对象
     * @return 响应对象
     */
    private static FierceResponse handleDefaultAction(FierceRequest request) {
        return FierceResponse.fail("Action[" + request.getAction() + "]不存在！");
    }
}
